home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / linux / tools / gtar10.lha / buffer.c < prev    next >
C/C++ Source or Header  |  1992-09-09  |  31KB  |  1,398 lines

  1. /* Buffer management for tar.
  2.    Copyright (C) 1988 Free Software Foundation
  3.  
  4. This file is part of GNU Tar.
  5.  
  6. GNU Tar is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GNU Tar is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Tar; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /*
  21.  * Buffer management for tar.
  22.  *
  23.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  24.  *
  25.  * @(#) buffer.c 1.28 11/6/87 - gnu
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <errno.h>
  30. #include <sys/types.h>        /* For non-Berkeley systems */
  31. #include <sys/stat.h>
  32. #include <signal.h>
  33.  
  34. #ifndef MSDOS
  35. #include <sys/ioctl.h>
  36. #if (!defined(USG) || defined(HAVE_MTIO)) && !defined(amigados)
  37. #include <sys/mtio.h>
  38. #endif
  39. #endif
  40.  
  41. #ifdef    MSDOS
  42. # include <fcntl.h>
  43. #include <process.h>
  44. #else
  45. # ifdef XENIX
  46. #  include <sys/inode.h>
  47. # endif
  48. # include <sys/file.h>
  49. #endif
  50.  
  51. extern int errno;
  52.  
  53. #include "tar.h"
  54. #include "port.h"
  55. #include "rmt.h"
  56. #include "regex.h"
  57.  
  58. /* Either stdout or stderr:  The thing we write messages (standard msgs, not
  59.    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
  60. #ifdef amigados
  61. FILE *msg_file = 0;
  62. #else
  63. FILE *msg_file = stdout;
  64. #endif
  65.  
  66. #define    STDIN    0        /* Standard input  file descriptor */
  67. #define    STDOUT    1        /* Standard output file descriptor */
  68.  
  69. #define    PREAD    0        /* Read  file descriptor from pipe() */
  70. #define    PWRITE    1        /* Write file descriptor from pipe() */
  71.  
  72. #ifdef __STDC__
  73. extern void    *malloc();
  74. extern void    *valloc();
  75. #else
  76. extern char    *malloc();
  77. extern char    *valloc();
  78. #endif
  79. extern time_t time();
  80.  
  81. extern char    *index(), *strcat();
  82. extern char    *strcpy();
  83.  
  84. /*
  85.  * V7 doesn't have a #define for this.
  86.  */
  87. #ifndef O_RDONLY
  88. #define    O_RDONLY    0
  89. #endif
  90. #ifndef O_RDWR
  91. #define O_RDWR        2
  92. #endif
  93. #ifndef O_CREAT
  94. #define O_CREAT        0
  95. #endif
  96. #ifndef O_BINARY
  97. #define O_BINARY    0
  98. #endif
  99.  
  100. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  101.                    it can't exec.  We hope compress/sh
  102.                    never return this status! */
  103.  
  104. void writeerror();
  105. void readerror();
  106.  
  107. void ck_pipe();
  108. void ck_close();
  109.  
  110. extern void finish_header();
  111. extern void to_oct();
  112.  
  113. #ifndef __MSDOS__
  114. /* Obnoxious test to see if dimwit is trying to dump the archive */
  115. dev_t ar_dev;
  116. ino_t ar_ino;
  117. #endif
  118.  
  119. /*
  120.  * The record pointed to by save_rec should not be overlaid
  121.  * when reading in a new tape block.  Copy it to record_save_area first, and
  122.  * change the pointer in *save_rec to point to record_save_area.
  123.  * Saved_recno records the record number at the time of the save.
  124.  * This is used by annofile() to print the record number of a file's
  125.  * header record.
  126.  */
  127. static union record **save_rec;
  128.  union record record_save_area;
  129. static long        saved_recno;
  130.  
  131. /*
  132.  * PID of child program, if f_compress or remote archive access.
  133.  */
  134. static int    childpid = 0;
  135.  
  136. /*
  137.  * Record number of the start of this block of records
  138.  */
  139. long    baserec;
  140.  
  141. /*
  142.  * Error recovery stuff
  143.  */
  144. static int    r_error_count;
  145.  
  146. /*
  147.  * Have we hit EOF yet?
  148.  */
  149. static int    eof;
  150.  
  151. /* JF we're reading, but we just read the last record and its time to update */
  152. extern time_to_start_writing;
  153. int file_to_switch_to= -1;    /* If remote update, close archive, and use
  154.                    this descriptor to write to */
  155.  
  156. static int volno = 1;        /* JF which volume of a multi-volume tape
  157.                    we're on */
  158.  
  159. char *save_name = 0;        /* Name of the file we are currently writing */
  160. long save_totsize;        /* total size of file we are writing.  Only
  161.                    valid if save_name is non_zero */
  162. long save_sizeleft;        /* Where we are in the file we are writing.
  163.                    Only valid if save_name is non-zero */
  164.  
  165. int write_archive_to_stdout;
  166.  
  167. /* Used by fl_read and fl_write to store the real info about saved names */
  168. static char real_s_name[NAMSIZ];
  169. static long real_s_totsize;
  170. static long real_s_sizeleft;
  171.  
  172. /* Reset the EOF flag (if set), and re-set ar_record, etc */
  173.  
  174. void
  175. reset_eof()
  176. {
  177.     if(eof) {
  178.         eof=0;
  179.         ar_record=ar_block;
  180.         ar_last=ar_block+blocking;
  181.         ar_reading=0;
  182.     }
  183. }
  184.  
  185. /*
  186.  * Return the location of the next available input or output record.
  187.  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
  188.  * it, to avoid accidentally going on to the next file on the "tape".
  189.  */
  190. union record *
  191. findrec()
  192. {
  193.     if (ar_record == ar_last) {
  194.         if (eof)
  195.             return (union record *)NULL;    /* EOF */
  196.         flush_archive();
  197.         if (ar_record == ar_last) {
  198.             eof++;
  199.             return (union record *)NULL;    /* EOF */
  200.         }
  201.     }
  202.     return ar_record;
  203. }
  204.  
  205.  
  206. /*
  207.  * Indicate that we have used all records up thru the argument.
  208.  * (should the arg have an off-by-1? XXX FIXME)
  209.  */
  210. void
  211. userec(rec)
  212.     union record *rec;
  213. {
  214.     while(rec >= ar_record)
  215.         ar_record++;
  216.     /*
  217.      * Do NOT flush the archive here.  If we do, the same
  218.      * argument to userec() could mean the next record (if the
  219.      * input block is exactly one record long), which is not what
  220.      * is intended.
  221.      */
  222.     if (ar_record > ar_last)
  223.         abort();
  224. }
  225.  
  226.  
  227. /*
  228.  * Return a pointer to the end of the current records buffer.
  229.  * All the space between findrec() and endofrecs() is available
  230.  * for filling with data, or taking data from.
  231.  */
  232. union record *
  233. endofrecs()
  234. {
  235.     return ar_last;
  236. }
  237.  
  238.  
  239. #if !defined(MSDOS) /* && !defined(amigados) */
  240. /*
  241.  * Duplicate a file descriptor into a certain slot.
  242.  * Equivalent to BSD "dup2" with error reporting.
  243.  */
  244. void
  245. dupto(from, to, msg)
  246.     int from, to;
  247.     char *msg;
  248. {
  249.     int err;
  250.  
  251.     if (from != to) {
  252.         err=close(to);
  253.         if(err<0 && errno!=EBADF) {
  254.             msg_perror("Cannot close descriptor %d",to);
  255.             exit(EX_SYSTEM);
  256.         }
  257.         err = dup(from);
  258.         if (err != to) {
  259.             msg_perror("cannot dup %s",msg);
  260.             exit(EX_SYSTEM);
  261.         }
  262.         ck_close(from);
  263.     }
  264. }
  265. #endif
  266.  
  267. #if defined(MSDOS) /* || defined(amigados) */
  268. void
  269. child_open()
  270. {
  271.     fprintf(stderr,"DOS %s can't use compressed or remote archives\n",tar);
  272.     exit(EX_ARGSBAD);
  273. }
  274. #else
  275. void
  276. child_open()
  277. {
  278.     int pipe[2];
  279.     int err = 0;
  280.  
  281.     int kidpipe[2];
  282.     int kidchildpid;
  283.  
  284. #define READ    0
  285. #define WRITE    1
  286.  
  287.     ck_pipe(pipe);
  288.  
  289. #ifdef amigados
  290.     childpid=vfork();
  291. #else
  292.     childpid=fork();
  293. #endif
  294.     if(childpid<0) {
  295.         msg_perror("cannot fork");
  296.         exit(EX_SYSTEM);
  297.     }
  298.     if(childpid>0) {
  299.         /* We're the parent.  Clean up and be happy */
  300.         /* This, at least, is easy */
  301.  
  302.         if(ar_reading) {
  303.             f_reblock++;
  304.             archive=pipe[READ];
  305.             ck_close(pipe[WRITE]);
  306.         } else {
  307.             archive = pipe[WRITE];
  308.             ck_close(pipe[READ]);
  309.         }
  310.         return;
  311.     }
  312.  
  313.     /* We're the kid */
  314.     if(ar_reading) {
  315.         dupto(pipe[WRITE],STDOUT,"(child) pipe to stdout");
  316.         ck_close(pipe[READ]);
  317.     } else {
  318.         dupto(pipe[READ],STDIN,"(child) pipe to stdin");
  319.         ck_close(pipe[WRITE]);
  320.     }
  321.  
  322.     /* We need a child tar only if
  323.        1: we're reading/writing stdin/out (to force reblocking)
  324.        2: the file is to be accessed by rmt (compress doesn't know how)
  325.        3: the file is not a plain file */
  326. #ifndef amigados
  327. #ifdef NO_REMOTE
  328.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))
  329. #else
  330.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))
  331. #endif
  332.     {
  333. #endif /* amigados */
  334.         /* We don't need a child tar.  Open the archive */
  335.         if(ar_reading) {
  336.             archive=open(ar_file, O_RDONLY|O_BINARY, 0666);
  337.             if(archive<0) {
  338.                 msg_perror("can't open archive %s",ar_file);
  339.                 exit(EX_BADARCH);
  340.             }
  341.             dupto(archive,STDIN,"archive to stdin");
  342.             /* close(archive); */
  343.         } else {
  344.             archive=creat(ar_file,0666);
  345.             if(archive<0) {
  346.                 msg_perror("can't open archive %s",ar_file);
  347.                 exit(EX_BADARCH);
  348.             }
  349.             dupto(archive,STDOUT,"archive to stdout");
  350.             /* close(archive); */
  351.         }
  352. #ifndef amigados
  353.     } else {
  354.         /* We need a child tar */
  355.         ck_pipe(kidpipe);
  356.  
  357.         kidchildpid=fork();
  358.         if(kidchildpid<0) {
  359.             msg_perror("child can't fork");
  360.             exit(EX_SYSTEM);
  361.         }
  362.  
  363.         if(kidchildpid>0) {
  364.             /* About to exec compress:  set up the files */
  365.             if(ar_reading) {
  366.                 dupto(kidpipe[READ],STDIN,"((child)) pipe to stdin");
  367.                 ck_close(kidpipe[WRITE]);
  368.                 /* dup2